package cn.wolfcode.wolf2w.redis.service.impl;

import cn.wolfcode.wolf2w.domain.Strategy;
import cn.wolfcode.wolf2w.redis.service.IStrategyStatisVORedisService;
import cn.wolfcode.wolf2w.redis.util.RedisKeys;
import cn.wolfcode.wolf2w.redis.vo.StrategyStatisVO;
import cn.wolfcode.wolf2w.service.IStrategyService;
import cn.wolfcode.wolf2w.util.DateUtil;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 攻略所需操作缓存的服务类
 */
@Service
public class StrategyStatisVORedisServiceImpl implements IStrategyStatisVORedisService {
    @Autowired
    private StringRedisTemplate template;
    @Autowired
    private IStrategyService strategyService;

    @Override
    public void viewnumIncrease(String sid, int num) {
        //首先根据sid拿取key
        StrategyStatisVO vo = this.getStrategyStatisVo(sid);
        //手动存入
        vo.setViewnum(vo.getViewnum() + num);
        this.setStrategyStatisVo(vo);
    }

    @Override
    public StrategyStatisVO getVo(String sid) {
        //组装key
        String key = RedisKeys.STRATEGY_STATIS_VO.join(sid);
        //拿对象
        String voJson = template.opsForValue().get(key);
        //转并返回
        return JSON.parseObject(voJson, StrategyStatisVO.class);
    }

    @Override
    public boolean favor(String sid, String uid) {
        //拿取数据统计对象
        StrategyStatisVO vo = this.getStrategyStatisVo(sid);
        //拼key
        String key = RedisKeys.USER_STRATEGY_FAVOR.join(uid);
        //从redis中查
        List<String> arrStra = new ArrayList<>();
        //从数据库中查响应Json字符串
        String listJson = template.opsForValue().get(key);
        if (StringUtils.hasLength(listJson)) {
            //数据库中有用户的list集合
            arrStra = JSON.parseArray(listJson, String.class);
        }
        //判断集合中是否有当前攻略id
        if (arrStra.contains(sid)) {
            //有:为取消收藏,将列表中移除该攻略id
            arrStra.remove(sid);
            //更新
            template.opsForValue().set(key, JSON.toJSONString(arrStra));
            //收藏数减1
            vo.setFavornum(vo.getFavornum() - 1);
            //更新
            this.setStrategyStatisVo(vo);
            return false;
        } else {
            //没有:为收藏
            arrStra.add(sid);
            //更新
            template.opsForValue().set(key, JSON.toJSONString(arrStra));
            //收藏数加1
            vo.setFavornum(vo.getFavornum() + 1);
            //更新
            this.setStrategyStatisVo(vo);
            return true;
        }
    }

    //抽方法,根据key快速获取vo对象
    @Override
    public StrategyStatisVO getStrategyStatisVo(String sid) {
        //从数据库中查响应Json字符串
        String key = RedisKeys.STRATEGY_STATIS_VO.join(sid);
        String redult = template.opsForValue().get(key);
        //如果能查到,直接加即可
        StrategyStatisVO vo = new StrategyStatisVO();
        if (StringUtils.hasLength(redult)) {
            vo = JSON.parseObject(redult, StrategyStatisVO.class);
        } else {
            //如果不能查到,手动从MongoDB中查
            Strategy strategy = strategyService.get(sid);
            //手动建StrategyStaticVO对象,手动+1,手动存入
            BeanUtils.copyProperties(strategy, vo);
            vo.setStrategyId(strategy.getId());
        }
        return vo;
    }

    //抽方法,将vo对象保存进redis中
    @Override
    public void setStrategyStatisVo(StrategyStatisVO vo) {
        String key = RedisKeys.STRATEGY_STATIS_VO.join(vo.getStrategyId());
        template.opsForValue().set(key, JSON.toJSONString(vo));
    }

    @Override
    public List<String> getUserStrategies(String userId) {
        //拼key
        String key = RedisKeys.USER_STRATEGY_FAVOR.join(userId);
        //从redis中查
        List<String> arrStra = Collections.EMPTY_LIST;
        //从数据库中查响应Json字符串
        String listJson = template.opsForValue().get(key);
        if (StringUtils.hasLength(listJson)) {
            arrStra = JSON.parseArray(listJson, String.class);
        }
        return arrStra;
    }

    @Override
    public void addCommentNum(String strategyId, int num) {
        StrategyStatisVO vo = this.getStrategyStatisVo(strategyId);
        vo.setReplynum(vo.getReplynum() + num);
        this.setStrategyStatisVo(vo);
    }

    @Override
    public boolean strategyThumbup(String sid, String uid) {
        //根据sid获取数据统计对象
        StrategyStatisVO vo = this.getStrategyStatisVo(sid);
        //根据uid+sid获取顶标记的key
        String key = RedisKeys.STRATEGY_THUMA.join(uid, sid);
        //判断标记key是否存在
        if (template.hasKey(key)) {
            //存在说明订过了,返回false,不做任何操作
            return false;
        } else {
            //不存在说明没有定国,设置有限期值
            Date date = new Date();
            Date endDate = DateUtil.getEndDate(date);
            long dateBetween = DateUtil.getDateBetween(endDate, date);
            template.opsForValue().set(key, "1", dateBetween, TimeUnit.SECONDS);
            //将顶数据加一
            vo.setThumbsupnum(vo.getThumbsupnum() + 1);
            //更新
            this.setStrategyStatisVo(vo);
            //返回true
            return true;
        }
    }

    @Override
    public boolean isStrategyVOExists(String sid) {
        String key = RedisKeys.STRATEGY_STATIS_VO.join(sid);
        if (template.hasKey(key)) {
            //如果有此key,返回true
            return true;
        }
        return false;
    }

    @Override
    public List<StrategyStatisVO> queryStartegyVoByPattern(String pattern) {
        List<StrategyStatisVO> vos = new ArrayList<>();
        //拼接key
        String key = RedisKeys.STRATEGY_STATIS_VO.join(pattern);
        //得到所有具体key
        Set<String> keys = template.keys(key);
        //遍历keys,拿取VO对象
        if (keys != null && keys.size() > 0) {
            for (String keyone : keys) {
                String voJson = template.opsForValue().get(keyone);
                if (StringUtils.hasLength(voJson)) {
                    StrategyStatisVO vo = JSON.parseObject(voJson, StrategyStatisVO.class);
                    vos.add(vo);
                }
            }
        }
        return vos;
    }
}
